package com.example.dingdong.shiro;

import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.http.HttpServletResponse;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.example.dingdong.daomain.BasicUserEntity;
import com.example.dingdong.repository.BasicUserRepository;
import com.example.dingdong.websocketService.WebSocketService;


/**
 * @ClassName: CustomCredentialsMatcher
 * @Description: 自定义认证加密方式
 * @Author :chengwenixng
 * @DateTime 2021-06-15 23:14:19
 */
public class CustomCredentialsMatcher extends SimpleCredentialsMatcher {

	private static final Logger log = LoggerFactory.getLogger(CustomCredentialsMatcher.class);

	@Autowired
	BasicUserRepository basicUserRepository;
	@Autowired
	private WebSocketService webSocketService;

	@Autowired
	private DefaultWebSessionManager defaultWebSessionManager;

	/**
	 * account-session(账号-session) 账号关联shiro Session
	 */
	private ConcurrentHashMap<String, Session> sessionMap = new ConcurrentHashMap<>();

	/**
	 * 登录类型（0-邮箱、1-身份证号、2-手机号、3-账号）
	 */
	private int loginType = 0;

	@Override
	public boolean doCredentialsMatch(AuthenticationToken authcToken, AuthenticationInfo info) {
		System.out.println("  authcToken =>>>>>>>>"+   authcToken);

		log.info("开始认证登录用户信息");
		UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
		
		System.out.println(" token =>>>>>>>>"+  token);


		// 1、检测用户是否存在
		String str = (String) info.getPrincipals().getPrimaryPrincipal();	
		System.out.println("str+++++++++++"+str);
		BasicUserEntity basicUserEntity = basicUserRepository.findByAccountAndDelFlag(str, true);
		if (basicUserEntity == null) {
			throw new AuthenticationException("用户不存在,请重新输入");
		}
		String phone = basicUserEntity.getPhone() != null ? basicUserEntity.getPhone() : "";
		String account = basicUserEntity.getAccount() != null ? basicUserEntity.getAccount() : "";
		String password = basicUserEntity.getPassword() != null ? basicUserEntity.getPassword() : "";

		// 3、校验密码是否正确
		if (equals(new String(token.getPassword()), basicUserEntity.getPassword())) {
			// 3.1、校验是否已经登录(若已经登录挤出之前的用户，重新登录)，同一用户只能一种方式登录}
			String userName = "";
			if (sessionMap.containsKey(account)) {
				userName = basicUserEntity.getAccount();
				removeSession(userName);
			}else if (sessionMap.containsKey(phone)) {
				userName = basicUserEntity.getPhone();
				removeSession(userName);
			} 

			String sessionAccount = basicUserEntity.getAccount();
			
			// 3.2、给当前登陆用户 session 会话存入对应属性，并设置过期时间
			Subject subject = SecurityUtils.getSubject();
			Session session = subject.getSession(true);
			session.setAttribute("user", basicUserEntity);
			session.setAttribute("account",sessionAccount);
			session.setAttribute("userId", basicUserEntity.getId());
			session.setAttribute("roleName", basicUserEntity.getRoleEntity().getRoleName());
			session.setTimeout(1800000);

			// 3.3、将当前登陆用户 账号-session 存入集合中
			sessionMap.put(sessionAccount,session);

			// 3.4、存储头部信息token
			ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
					.getRequestAttributes();
			HttpServletResponse response = requestAttributes.getResponse();
			String xAuthToken = String.valueOf(session.getId());
			response.setHeader("x-auth-token", xAuthToken);

			// 3.5、存储 websocket 所需要的token值
			webSocketService.getAccountrelateIpAddress().put(sessionAccount, xAuthToken);
		} else {
			throw new AuthenticationException("密码错误");
		}
		return equals(new String(token.getPassword()), password);
	}

	public ConcurrentHashMap<String, Session> getSessionMap() {
		return sessionMap;
	}

	/**
	 * 
	 * @Title: removeSession
	 * @Description: 
	 * @Author coding
	 * @DateTime 2021-06-15 23:14:06
	 * @param userName
	 */
	public void removeSession(String userName) {
		try {
			Session session = sessionMap.get(userName);
			defaultWebSessionManager.getSessionDAO().delete(session);
		} catch (Exception e) {
			log.warn("用户已经退出!");
		}
		String oldToken = webSocketService.getAccountrelateIpAddress().get(userName);
		try {
			webSocketService.addJsonObjToSendUnicast("checkLogin", null, oldToken);
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 3.2、移除之前储存的用户名和sesion的键值对
		sessionMap.remove(userName);
		log.warn("重复用户登录注销:" + userName);
	}

}
